﻿#region Copyright (c) 2008 plexBB Team

/*  Copyright (c) 2008 plexBB Team
 *  
 *  This file is free software: you may copy, redistribute and/or modify it  
 *  under the terms of the GNU General Public License as published by the  
 *  Free Software Foundation, either version 2 of the License, or (at your  
 *  option) any later version.  
 *  
 *  This file is distributed in the hope that it will be useful, but  
 *  WITHOUT ANY WARRANTY; without even the implied warranty of  
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
 *  General Public License for more details.  
 *  
 *  You should have received a copy of the GNU General Public License  
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */

#endregion

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using PlexBB.Data;

namespace PlexBB.Controls.Admin.ModuleManagement
{
    public abstract class AcpModulesList : AcpModuleControlBase
    {
        #region Controls

        protected IButtonControl bDeleteModule;
        protected IButtonControl bDisableModule;
        protected HyperLink hEditModule;
        protected IButtonControl bEnableModule;
        protected Control cErrorBox;
        protected ITextControl tError;
        protected Control cModuleActions;
        protected Repeater rModules;
        protected Repeater rNavigation;

        #endregion

        protected ModuleType ModuleType
        {
            get
            {
                switch (CurrentModule.ModuleMode)
                {
                    case "acp":
                        return ModuleType.Acp;
                    case "mcp":
                        return ModuleType.Mcp;
                    case "ucp":
                        return ModuleType.Ucp;
                    default:
                        throw new NotSupportedException();
                }
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            if (!IsPostBack)
            {
                DataBindRepeaters();
                hEditModule.NavigateUrl = CreateUrl(ParentModuleID, ParentModuleID);
            }
            rModules.ItemCommand += rModules_ItemCommand;
            bDeleteModule.Click += bDeleteModule_Click;
            bDisableModule.Click += bDisableModule_Click;
            bEnableModule.Click += bEnableModule_Click;
            base.OnLoad(e);
        }

        private void bDisableModule_Click(object sender, EventArgs e)
        {
            ParentModule.Enabled = false;
            Data.SubmitChanges();
            InvalidateModulesCache();
        }

        private void bEnableModule_Click(object sender, EventArgs e)
        {
            ParentModule.Enabled = true;
            Data.SubmitChanges();
            InvalidateModulesCache();
        }

        private void bDeleteModule_Click(object sender, EventArgs e)
        {
            DeleteModule(ParentModule);
        }

        private void DeleteModule(Module module)
        {
            // show confirm text
            ShowConfirm(Lang["DELETE_MODULE"], Lang["DELETE_MODULE_CONFIRM"], "Delete", module.ModuleID);
        }

        private void DataBindRepeaters()
        {
            rModules.ItemDataBound += rModules_ItemDataBound;
            rModules.DataSource = (from m in Data.Modules
                                   where m.ModuleType == ModuleType && Equals(m.ParentID, ParentModuleID)
                                   orderby m.Position
                                   select m).ToList();
            rModules.DataBind();

            List<Module> parentModules = new List<Module>();
            if (ParentModule != null)
            {
                Module parent = ParentModule.ParentModule;
                while (parent != null)
                {
                    parentModules.Insert(0, parent);
                    parent = parent.ParentModule;
                }
                parentModules.Insert(0, null);
            }
            rNavigation.ItemDataBound += rNavigation_ItemDataBound;
            rNavigation.DataSource = parentModules;
            rNavigation.DataBind();
        }

        private void rNavigation_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            Module module = (Module)e.Item.DataItem;

            HyperLink hNavigate = e.Item.Find<HyperLink>("hNavigate");
            if (hNavigate != null)
            {
                if (module == null)
                {
                    hNavigate.Text = ModuleType.ToString().ToUpper();
                    hNavigate.NavigateUrl = CreateUrl(null, null);
                }
                else
                {
                    hNavigate.Text = Lang[module.LangName];
                    hNavigate.NavigateUrl = CreateUrl(module.ModuleID, null);
                }
            }

            Label lCurrentModule = e.Item.Find<Label>("lCurrentModule");
            if (lCurrentModule != null)
            {
                lCurrentModule.Text = ParentModule == null ? ModuleType.ToString().ToUpper() : Lang[ParentModule.LangName];
            }
        }

        private void rModules_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem)
            {
                return;
            }

            Module module = (Module)e.Item.DataItem;

            #region iModuleImage
            Image iModuleImage = e.Item.Find<Image>("iModuleImage");
            if (!module.Enabled)
            {
                iModuleImage.ImageUrl = PlexBB.ResolveThemeUrl("images/IconFolderLock.gif");
                iModuleImage.AlternateText = Lang["DEACTIVATED_MODULE"];
            }
            else if (module.IsCategory)
            {
                iModuleImage.ImageUrl = PlexBB.ResolveThemeUrl("images/IconSubfolder.gif");
                iModuleImage.AlternateText = Lang["CATEGORY"];
            }
            else
            {
                iModuleImage.ImageUrl = PlexBB.ResolveThemeUrl("images/IconFolder.gif");
                iModuleImage.AlternateText = Lang["MODULE"];
            }

            #endregion

            #region hModuleTitle

            HyperLink hModuleTitle = e.Item.Find<HyperLink>("hModuleTitle", true);
            hModuleTitle.Text = Lang[module.LangName];
            hModuleTitle.NavigateUrl = CreateUrl(module.ModuleID, null);

            #endregion

            #region cHiddenModule

            Control cHiddenModule = e.Item.Find<Control>("cHiddenModule");
            cHiddenModule.Visible = !module.Display;

            #endregion

            #region bDisable

            IButtonControl bDisable = e.Item.Find<IButtonControl>("bDisable");
            bDisable.CommandName = "Disable";
            bDisable.CommandArgument = module.ModuleID.ToString();
            ((Control)bDisable).Visible = module.Enabled;

            #endregion

            #region bEnable

            IButtonControl bEnable = e.Item.Find<IButtonControl>("bEnable");
            bEnable.CommandName = "Enable";
            bEnable.CommandArgument = module.ModuleID.ToString();
            ((Control)bEnable).Visible = !module.Enabled;

            #endregion

            bool firstRow = e.Item.ItemIndex == 0;
            bool lastRow = e.Item.ItemIndex == ((IList)rModules.DataSource).Count - 1;

            #region bUp

            IButtonControl bUp = e.Item.Find<IButtonControl>("bUp");
            bUp.CommandName = "Up";
            bUp.CommandArgument = module.ModuleID.ToString();
            ((Control)bUp).Visible = !firstRow;

            #endregion

            #region cUpDisabled

            Control cUpDisabled = e.Item.Find<Control>("cUpDisabled");
            cUpDisabled.Visible = firstRow;

            #endregion

            #region bDown

            IButtonControl bDown = e.Item.Find<IButtonControl>("bDown");
            bDown.CommandName = "Down";
            bDown.CommandArgument = module.ModuleID.ToString();
            ((Control)bDown).Visible = !lastRow;

            #endregion

            #region cDownDisabled

            Control cDownDisabled = e.Item.Find<Control>("cDownDisabled");
            cDownDisabled.Visible = lastRow;

            #endregion

            #region hEdit
            HyperLink hEdit = e.Item.Find<HyperLink>("hEdit");
            hEdit.NavigateUrl = CreateUrl(ParentModuleID, module.ModuleID);

            #endregion

            //#region bEdit

            //IButtonControl bEdit = e.Item.Find<IButtonControl>("bEdit");
            //bEdit.CommandName = "Edit";
            //bEdit.CommandArgument = module.ModuleID.ToString();

            //#endregion

            #region bDelete

            IButtonControl bDelete = e.Item.Find<IButtonControl>("bDelete");
            bDelete.CommandName = "Delete";
            bDelete.CommandArgument = module.ModuleID.ToString();

            #endregion
        }

        private void rModules_ItemCommand(object source, RepeaterCommandEventArgs e)
        {
            Module module = Data.Modules.Single(m => m.ModuleID == Convert.ToInt64(e.CommandArgument));

            // using object.Equals to make LINQ correctly translate NULL value
            // used in Up/Down only
            IQueryable<Module> siblingModules = from m in Data.Modules
                                                where Equals(m.ParentModule, module.ParentModule) && m.ModuleType == module.ModuleType
                                                select m;
            switch (e.CommandName)
            {
                case "Disable":
                    module.Enabled = false;
                    break;
                case "Enable":
                    module.Enabled = true;
                    break;
                case "Up":
                    {
                        Module exchangeModule = (from m in siblingModules
                                                 where m.Position < module.Position
                                                 orderby m.Position descending
                                                 select m).First();
                        int exchangeModulePosition = exchangeModule.Position;
                        exchangeModule.Position = module.Position;
                        module.Position = exchangeModulePosition;
                    }
                    break;
                case "Down":
                    {
                        Module exchangeModule = (from m in siblingModules
                                                 where m.Position > module.Position
                                                 orderby m.Position
                                                 select m).First();
                        int exchangeModulePosition = exchangeModule.Position;
                        exchangeModule.Position = module.Position;
                        module.Position = exchangeModulePosition;
                    }
                    break;
                case "Delete":
                    DeleteModule(module);
                    break;
                default:
                    throw new NotSupportedException();
            }
            Data.SubmitChanges();

            // rebind dependent
            DataBindRepeaters();
            InvalidateModulesCache();
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            if (ParentModule != null && ParentModule.Modules.Count == 0)
            {
                cModuleActions.Visible = true;
                if (bEnableModule != null)
                {
                    ((Control)bEnableModule).Visible = !ParentModule.Enabled;
                }

                if (bDisableModule != null)
                {
                    ((Control)bDisableModule).Visible = ParentModule.Enabled;
                }
            }
            else
            {
                cModuleActions.Visible = false;
            }
            rModules.Visible = rModules.Items.Count > 0;
            cErrorBox.Visible = tError.Text.Length > 0;
        }

        private void InvalidateModulesCache()
        {
            GlobalSetting setting = Data.GlobalSettings.SingleOrDefault(s => s.Name == GlobalSetting.CachedModulesVersion);
            if (setting == null)
            {
                setting = new GlobalSetting { Name = GlobalSetting.CachedModulesVersion };
                Data.GlobalSettings.InsertOnSubmit(setting);
            }
            setting.Value = Guid.NewGuid().ToString("N");
            Data.SubmitChanges();

            ((Acp)PlexBB.ActionControl).InvalidateCachedModules();
        }

        protected override void OnConfirmYesClick(object sender, ConfirmEventArgs e)
        {
            base.OnConfirmYesClick(sender, e);
            switch (e.ConfirmCommand)
            {
                case "Delete":
                    // delete module
                    Module module = Data.Modules.Single(m => m.ModuleID == (long)e.ConfirmArgument);
                    if (module.Modules.Count > 0)
                    {
                        tError.Text = Lang["CANNOT_REMOVE_MODULE"];
                    }
                    else
                    {
                        int? parentModuleID = module == ParentModule ? ParentModule.ParentID : ParentModuleID;
                        ShowMessage(null, Lang["MODULE_DELETED"], CreateUrl(parentModuleID, null), true, true);
                        Data.Modules.DeleteOnSubmit(module);
                        Data.SubmitChanges();
                        InvalidateModulesCache();
                        //if (module == ParentModule)
                        //{
                        //    ParentModuleID = ParentModule.ParentID;
                        //    DataBindRepeaters();
                        //}
                    }
                    break;
                default:
                    throw new NotSupportedException();
            }
        }

    }
}